package cn.seqdata.forecast.model.smoothing;

import cn.seqdata.forecast.model.AbstractModel;
import cn.seqdata.forecast.model.ModelParams;
import org.hawkular.datamining.forecast.AutomaticForecaster;
import org.hawkular.datamining.forecast.DataPoint;
import org.hawkular.datamining.forecast.Forecaster.Config;
import org.hawkular.datamining.forecast.ImmutableMetricContext;
import org.hawkular.datamining.forecast.MetricContext;
import org.hawkular.datamining.forecast.models.TimeSeriesModel;
import org.hawkular.datamining.forecast.utils.JodaUtils;
import org.joda.time.ReadableInterval;
import org.joda.time.ReadablePeriod;

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

/**
 * @author jrxian
 */
public abstract class ExponentialSmoothingModel extends AbstractModel<ModelParams> {
    protected AutomaticForecaster forecaster;
    protected MetricContext context = ImmutableMetricContext.getDefault();
    protected Config config = Config.getDefault();

    protected void create(org.hawkular.datamining.forecast.models.Model model, ModelParams params){
        config.setModelToUse(model);

        setParams(params);

        ReadableInterval interval = getParams().getInterval();
        ReadablePeriod period = getParams().getPeriod();
        int size = JodaUtils.size(interval, period);

        config.setPeriod(size);
    }

    protected void setForecaster(AutomaticForecaster forecaster){
        this.forecaster = forecaster;
    }

    @Override
    public void setParams(ModelParams params) {
        super.setParams(params);
    }

    @Override
    public void learn(double[] values) {
        List<DataPoint> dps = new ArrayList<>(values.length);

        for (int i = 0; i < values.length; ++i) {
            dps.add(new DataPoint(values[i], (long) i));
        }

        forecaster.learn(dps);
    }

    @Override
    public double[] forecast(int n) {
        List<DataPoint> dps = forecaster.forecast(n);
        double[] vals = new double[dps.size()];

        ListIterator<DataPoint> i$ = dps.listIterator();
        while (i$.hasNext()) {
            int i = i$.nextIndex();
            DataPoint dp = i$.next();
            vals[i] = dp.getValue();
        }

        return vals;
    }
}
